package com.sky.robot.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.sky.robot.bo.CodeGeneratorBo;
import com.sky.robot.consts.CoreConst;
import com.sky.robot.domain.SkyComponentDo;
import com.sky.robot.entity.*;
import com.sky.robot.generator.MyAutoGenerator;
import com.sky.robot.service.*;
import com.sky.robot.utils.*;
import com.sky.robot.vo.CodeGeneratorRequestVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.python.core.PyFunction;
import org.python.core.PyList;
import org.python.core.PyObject;
import org.python.util.PythonInterpreter;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;

import java.io.*;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;

@Service
@Slf4j
public class SkyRobotServiceImpl implements SkyRobotService {


    @Autowired
    private SkyFuncFormBtnService skyFuncFormBtnService;

    @Autowired
    private SkyFuncFormService skyFuncFormService;

    @Autowired
    private SkyFuncService skyFuncService;

    @Autowired
    private SkyTableColumnService skyTableColumnService;

    @Autowired
    private ResourceLoader resourceLoader;

    @Autowired
    private SkyFuncFormItemService skyFuncFormItemService;

    @Autowired
    private SkyFuncFormCompService skyFuncFormCompService;

    /**
     * 返回列表字段配置
     * 返回卡片字段配置
     */
    @Override
    public Map<String, Object> getInitConfig(SkyComponentDo skyComponentDo) {
        List<Object> dataListConfig = new ArrayList<>(); // 列表字段配置
        List<Object> cardListConfig = new ArrayList<>(); // 卡片字段配置
        // 初始化基础数据
        String formId = "";
        String functionId = "";


        Map<String, Object> map = new HashMap<>();

        map.put("dataListConfig", dataListConfig); // 列表字段配置
        map.put("cardListConfig", cardListConfig); // 卡片字段配置

        return map;
    }


    /**
     * 通过functionId抓取对应的数据
     */
    @Override
    public Map<String, Object> getInitConfig(String functionId) {


        return null;
    }


    @Override
    public Result<Void> codeGenerator(CodeGeneratorRequestVo requestVo) {

        CodeGeneratorBo bo = new CodeGeneratorBo();

        BeanUtils.copyProperties(requestVo, bo);

        handleDb(requestVo, bo);
        handleTable(requestVo, bo);

        return execute(bo);

    }


    /**
     * 执行python脚本
     * */
    @Override
    public Object executorPy(Map<String, Object> promptMap) throws IOException, InterruptedException {
        String fileContent = getFileContent("\\py\\1.py");

        String pythonPath = "C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python312\\python.exe";
        System.setProperty("python.cachedir", pythonPath);

        PythonInterpreter pythonInterpreter = new PythonInterpreter();
        PythonInterpreter.initialize(System.getProperties(), System.getProperties(), new String[0]);

        String prompt = promptMap.get("prompt").toString();

        List<String> itemList = new ArrayList<>();

        itemList.add(prompt);

        pythonInterpreter.execfile(fileContent); // 传入一个文件的绝对路径

        PyFunction function = pythonInterpreter.get("get_completion", PyFunction.class);

        PyObject pyObject = function.__call__(new PyList(itemList));

        System.out.println(pyObject.toString());

        return pyObject.toString();
    }

    @Override
    public Object send(Map<String, Object> promptMap) {
        String apiEndpoint = "https://api.openai.com/v1/chat/completions";
        String apiKey = "sk-XelpeD1K6Q5o9GjxfppXLF2alR8aZeThffX4W6gTqJslYIDy"; // 请替换为你的API密钥

        try {
            URL url = new URL(apiEndpoint);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            // 设置请求头
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Authorization", "Bearer " + apiKey);
            conn.setRequestProperty("Content-Type", "application/json");
            // 设置请求体
            String data = JSONUtils.map2String(promptMap);
            // String data = `{"prompt": "What is the weather like today?", "max_tokens": 50}`
            conn.setDoOutput(true);
            OutputStream outputStream = conn.getOutputStream();
            outputStream.write(data.getBytes());
            outputStream.flush();
            // 发送请求并获取响应
            int responseCode = conn.getResponseCode();
            BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()
            ));
            String line;
            StringBuilder response = new StringBuilder();
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
            reader.close();
            // 处理响应
            if (responseCode == 200) {
                System.out.println("响应结果：" + response.toString());
                return response.toString();
                // 在这里对响应进行进一步处理
            } else {
                System.out.println("调用ChatGPT接口失败，HTTP状态码：" + responseCode);
            }
            conn.disconnect();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "处理失败";
    }

    /**
     * 根据前端传入的数据保存配置项
     * 0、将原数组存储到数据库中，并且进行排序
     * 1、根据现在已有的数组，将同一个FormID下的组件进行区分，一个FormID下只能有一个表格
     * 2、FormID下的组件进行分解，将对应的组件分解成form的Item和Button；item和button中需要加上对应的组件来源
     * 3、通过组件的code可以删除或者插入对应的按钮或者字段
     * 4、FormID需求类型，是表格类型还是树形
     */
    @Override
    public Map<String, Object> saveInitConfig(Map<String, Object> map) {
        Map<String, Object> resultMap = new HashMap<>();
        // 0、将原数组存储到数据库中，并且进行排序
        List componentList = (List) map.get("componentList");
        // 给出一个map存储对应的FormID对应的组件映射
        Map<String, List<SkyFuncFormComp>> compMap = new HashMap<>();
        List<SkyFuncFormComp> compList = new ArrayList<>();
        for (Object o : componentList) {
            // 获取每一个组件
            SkyFuncFormComp skyFunctionItem = JSONObject.parseObject(JSONObject.toJSONString(o), SkyFuncFormComp.class);
            Integer sort = skyFunctionItem.getSort();
            if (sort == null) {
                skyFunctionItem.setSort(Integer.MAX_VALUE);
            }
            compList.add(skyFunctionItem);

            String formId = skyFunctionItem.getFormId();
            List<SkyFuncFormComp> skyFuncFormComps = compMap.get(formId);
            if (skyFuncFormComps == null) {
                skyFuncFormComps = new ArrayList<>();
            }
            skyFuncFormComps.add(skyFunctionItem);

            String componentType = skyFunctionItem.getComponentType();
            if (org.apache.commons.lang3.StringUtils.isBlank(formId) && !CoreConst.MY_CONTAINER.equals(componentType)) {
                // 容器可以为空，但是不是容器FormID为空不加入数据库
                continue;
            }
            // 1、根据现在已有的数组，将同一个FormID下的组件进行区分，一个FormID下只能有一个表格
            compMap.put(formId, skyFuncFormComps);
        }
        // 对组件进行排序
        Comparator<SkyFuncFormComp> compComparator = Comparator.comparing(SkyFuncFormComp::getSort);
        compList.sort(compComparator);

        // 校验是否有表单绑定了多个FormID
        Set<String> formIdSet = compMap.keySet();
        for (String formId : formIdSet) {
            List<SkyFuncFormComp> funcFormComps = compMap.get(formId);
            int count = 0;
            for (SkyFuncFormComp funcFormComp : funcFormComps) {
                String componentType = funcFormComp.getComponentType();
                String newFormId = funcFormComp.getFormId();
                if (count > 1) {
                    // 有的表格绑定了多个FormID
                    resultMap.put("msg", "一个form绑定了多个表格");
                    return resultMap;
                }
                // 如果是表格
                if (CoreConst.MY_TABLE.equals(componentType) && !org.apache.commons.lang3.StringUtils.isBlank(newFormId)) {
                    count++;
                }
            }
            if (count == 0) {
                // TODO:没有绑定表格，这里没有考虑没有表格的页面
                resultMap.put("msg", "一个form至少绑定一个表格");
                return resultMap;
            }
        }

        // 将组将绑定FormID，存储为现有结果，后续支撑返回前端
        Object item = saveCompItem(map, compList);


        return null;
    }

    /**
     * 保存表单
     */
    private Object saveCompItem(Map<String, Object> map, List<SkyFuncFormComp> skyFuncFormComps) {
        String functionId = (String) map.get("functionId");
        if (org.apache.commons.lang3.StringUtils.isBlank(functionId)) {
//            throw new BaseException("functionId不能为空");
        }
        List<SkyFuncFormComp> otherComp = new ArrayList<>();
        // 保存组件
        List<SkyFuncFormComp> skyNewFuncFormComps = saveComp(skyFuncFormComps);

        for (SkyFuncFormComp skyFuncFormComp : skyNewFuncFormComps) {
            String mainType = skyFuncFormComp.getMainType(); // 主要的类型0:列表1:卡片
            String childType = skyFuncFormComp.getChildType(); // 0:单表单1:树形
            String componentType = skyFuncFormComp.getComponentType();
            // 处理容器
            if (CoreConst.MY_CONTAINER.equals(componentType)) {
                System.out.println("挂载容器");
            }
            // 表格
            else if (CoreConst.MY_TABLE.equals(componentType)) {
                // 按照字段，将对应的字段和按钮直接全量加载到数据库中，并且标记出来源
                if (CoreConst.COMP_TABLE_TYPE_MAIN.equals(skyFuncFormComp.getTableType())) {
                    saveMainTableItemBtn(skyFuncFormComp);
                } else {
                    saveSelfTableItemBtn(skyFuncFormComp);
                }
            }
            // 按钮
            else if (CoreConst.MY_BUTTON.equals(componentType)) {
                otherComp.add(skyFuncFormComp);
            } else {
                System.out.println("暂不支持" + componentType + "类型挂载到" + (("0".equals(mainType)) ? "卡片" : "列表") + "上");
            }
        }
        // 保存其他组件
        saveOtherComp(otherComp);


        return null;
    }

    private List<SkyFuncFormComp> saveComp(List<SkyFuncFormComp> skyFuncFormComps) {
        String idStr = IdWorker.getIdStr();
        for (SkyFuncFormComp skyFuncFormComp : skyFuncFormComps) {
            skyFuncFormComp.setTempCode(idStr);
            skyFuncFormCompService.add(skyFuncFormComp);
        }
        LambdaQueryWrapper<SkyFuncFormComp> funcFormCompLambdaQueryWrapper = new LambdaQueryWrapper<>();
        funcFormCompLambdaQueryWrapper.eq(SkyFuncFormComp::getTempCode, idStr);
        return skyFuncFormCompService.list(funcFormCompLambdaQueryWrapper);
    }

    /**
     * 处理没有绑定的组件入口
     */
    private void saveOtherComp(List<SkyFuncFormComp> otherComp) {
        int curr = 10;
        // 将拖拽的按钮添加到form中
        for (SkyFuncFormComp skyFuncFormComp : otherComp) {
            String componentType = skyFuncFormComp.getComponentType();
            // 处理其他没有绑定的按钮
            if (CoreConst.MY_BUTTON.equals(componentType)) {
                saveBtnComp(skyFuncFormComp);
            }
        }


        curr += 5;
    }

    // 将全量的数据按照模板进行生成
    private void saveMainTableItemBtn(SkyFuncFormComp skyFuncFormComp) {
        String componentId = skyFuncFormComp.getId(); // 组件ID
        String functionId = skyFuncFormComp.getFunctionId();
        String formId = skyFuncFormComp.getFormId();
        SkyFunc skyFunc = skyFuncService.getById(functionId);
        SkyFuncForm skyFuncForm = skyFuncFormService.getById(formId);
        if (skyFunc == null || skyFuncForm == null) {
            return;
        }
        String tableName = skyFuncForm.getTableName(); // 取的是哪个数据表
        // 取出表对应的字段信息，将字段信息按照规则插入到sky_func_form_item中
        LambdaQueryWrapper<SkyTableColumn> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SkyTableColumn::getTableName, tableName);
        List<SkyTableColumn> list = skyTableColumnService.list(queryWrapper);
        if (list.size() == 0) {
            return;
        }
        // 查询form有没有对应的配置，如果有就删除
        List<SkyFuncFormItem> funcFormItemList = getFuncFormItem(list, formId, functionId, componentId);
        // 将配置项插入到系统
        deleteFuncFormItem(formId, functionId, componentId);
        funcFormItemList.forEach(item -> skyFuncFormItemService.add(item));
        // 查询全部的默认按钮
        LambdaQueryWrapper<SkyFuncFormBtn> skyFuncFormBtnLambdaQueryWrapper = new LambdaQueryWrapper<>();
        skyFuncFormBtnLambdaQueryWrapper.eq(SkyFuncFormBtn::getStatus, CoreConst.BYN_STATUS_SYS_TEM);
        List<SkyFuncFormBtn> funcFormBtnList = skyFuncFormBtnService.list(skyFuncFormBtnLambdaQueryWrapper);
        // 处理对应的按钮数据
        List<SkyFuncFormBtn> formBtnList = getFuncFormBtn(funcFormBtnList, formId, functionId, componentId);
        deleteFuncFormBtn(formId, functionId, componentId);
        formBtnList.forEach(item -> skyFuncFormBtnService.add(item));
    }


    /**
     * 处理没有绑定的按钮
     */
    private void saveBtnComp(SkyFuncFormComp formComp) {
        SkyFuncFormBtn skyFuncFormBtn = new SkyFuncFormBtn();
        skyFuncFormBtn.setFunctionId(formComp.getFunctionId());
        skyFuncFormBtn.setFormId(formComp.getFormId());
        skyFuncFormBtn.setStatus(CoreConst.BYN_STATUS_SYS_SELF);
        skyFuncFormBtnService.add(skyFuncFormBtn);
    }


    /**
     * 删除按钮
     */
    private void deleteFuncFormBtn(String formId, String functionId, String componentId) {
        LambdaQueryWrapper<SkyFuncFormBtn> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SkyFuncFormBtn::getFormId, formId);
        queryWrapper.eq(SkyFuncFormBtn::getFunctionId, functionId);
        queryWrapper.eq(SkyFuncFormBtn::getCompId, componentId);
        List<SkyFuncFormBtn> list = skyFuncFormBtnService.list(queryWrapper);
        list.forEach(item -> skyFuncFormBtnService.deleteBatch(item.getId()));
    }

    /**
     * 删除item
     */
    private void deleteFuncFormItem(String formId, String functionId, String componentId) {
        LambdaQueryWrapper<SkyFuncFormItem> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SkyFuncFormItem::getFormId, formId);
        queryWrapper.eq(SkyFuncFormItem::getFunctionId, functionId);
        queryWrapper.eq(SkyFuncFormItem::getCompId, componentId);
        List<SkyFuncFormItem> list = skyFuncFormItemService.list(queryWrapper);
        list.forEach(item -> skyFuncFormItemService.deleteBatch(item.getId()));
    }

    /**
     * 组装按钮数据
     */
    private List<SkyFuncFormBtn> getFuncFormBtn(List<SkyFuncFormBtn> funcFormBtnList, String formId, String functionId, String componentId) {
        List<SkyFuncFormBtn> skyFuncFormBtns = new ArrayList<>();
        for (SkyFuncFormBtn skyFuncFormBtn : funcFormBtnList) {
            skyFuncFormBtn.setFormId(formId);
            skyFuncFormBtn.setFunctionId(functionId);
            skyFuncFormBtn.setStatus("1");
            skyFuncFormBtn.setCompId(componentId);
            skyFuncFormBtn.setId(IdWorker.getIdStr());
            skyFuncFormBtns.add(skyFuncFormBtn);
        }
        return skyFuncFormBtns;
    }

    /**
     * 组织formItem的结构
     */
    private List<SkyFuncFormItem> getFuncFormItem(List<SkyTableColumn> skyTableColumns, String formId, String functionId, String componentId) {
        List<SkyFuncFormItem> funcFormItems = new ArrayList<>();
        int curr = 10;
        for (SkyTableColumn skyTableColumn : skyTableColumns) {
            // 将表字段信息copy到formItem中
            SkyFuncFormItem skyFuncFormItem = new SkyFuncFormItem();
            BeanUtils.copyProperties(skyTableColumn, skyFuncFormItem);
            skyFuncFormItem.setFormId(formId);
            skyFuncFormItem.setFunctionId(functionId);
            String colCode = skyTableColumn.getColCode();
            String attrName = CoreUtils.columnToJava(colCode);
            skyFuncFormItem.setId(IdWorker.getIdStr());
            skyFuncFormItem.setItemCode(attrName);//表单编码
            skyFuncFormItem.setItemType("T");//表单类型
            skyFuncFormItem.setIsUse("1");//是否启用
            skyFuncFormItem.setInputElement("input");//输入元素
            skyFuncFormItem.setItemConfig("");//输入配置
            skyFuncFormItem.setIsList("1");//是否列表字段
            skyFuncFormItem.setListEdit("0");//默认不可列表修改
            skyFuncFormItem.setListHide("0");
            skyFuncFormItem.setItemWidth("150");//列宽
            skyFuncFormItem.setListOrder(10 + curr);//列表排序
            skyFuncFormItem.setIsQuery("0");//是否快速查询项
            skyFuncFormItem.setQueryType("likeStr");//查询类型  默认模糊查询
            skyFuncFormItem.setAlignType("C");//列表对齐方式
            skyFuncFormItem.setIsCard("1");//是否卡片字段
            skyFuncFormItem.setCardColumn(1);//占卡片列数
            skyFuncFormItem.setCardOrder(10 + curr);//卡片排序
            skyFuncFormItem.setCardHide("0,0,0");//卡片隐藏
            skyFuncFormItem.setInputWidth(100);//输入框长度
            skyFuncFormItem.setItemReadonly("0,0,1");//是否只读 初始状态查看页面只读
            skyFuncFormItem.setCompId(componentId);
            switch (attrName) {
                case "updateTime":
                case "updateBy":
                case "createTime":
                case "createBy":
                    skyFuncFormItem.setCardHide("1,1,1");//卡隐藏

                    skyFuncFormItem.setItemReadonly("1,1,1");//只读

                    break;
                case "audTime":
                case "audUser":
                    skyFuncFormItem.setCardHide("1,1,1");//卡隐藏

                    break;
                case "audFlag":
                    skyFuncFormItem.setCardHide("1,1,1");//卡隐藏

                    skyFuncFormItem.setInputElement("select");//输入元素

                    break;
                case "id":
                case "tenantId":
                case "delFlag":
                    skyFuncFormItem.setCardHide("1,1,1");//卡隐藏

                    skyFuncFormItem.setListHide("1");//列表隐藏

                    break;
                case "createName":
                case "updateName":
                    skyFuncFormItem.setCardHide("1,1,1");//卡隐藏

                    skyFuncFormItem.setListHide("1");//列表隐藏

                    break;
            }
            funcFormItems.add(skyFuncFormItem);
            curr += 5;
        }

        return funcFormItems;
    }

    private void saveSelfTableItemBtn(SkyFuncFormComp skyFuncFormComp) {
    }


    /**
     * 执行生成后台代码
     */
    private Result<Void> execute(CodeGeneratorBo bo) {
        try {
            new MyAutoGenerator(bo).execute();
            return Result.success();
        } catch (Exception e) {
            String errMsg = ExceptionUtils.getStackTrace(e);
            log.error(errMsg);
        }
        return Result.success();
    }

    // 处理数据库
    private void handleDb(CodeGeneratorRequestVo requestVo, CodeGeneratorBo bo) {
        String dbUrl = "";
        String username = requestVo.getUsername();
        String password = requestVo.getPassword();
        String driver = "";
        if (!StringUtils.hasText(requestVo.getDbTypeName())
                || DbType.getDbType(requestVo.getDbTypeName()) == DbType.MYSQL) {
            // mysql
            dbUrl = "jdbc:mysql://" + requestVo.getHost() + "/" + requestVo.getDbName();
            driver = "com.mysql.cj.jdbc.Driver";
        } else if (DbType.getDbType(requestVo.getDbTypeName()) == DbType.ORACLE) {
            dbUrl = "jdbc:oracle:thin:@" + requestVo.getHost() + ":" + requestVo.getDbName();
            driver = "oracle.jdbc.OracleDriver";
        } else if (DbType.getDbType(requestVo.getDbTypeName()) == DbType.SQL_SERVER) {
            dbUrl = "jdbc:sqlserver://" + requestVo.getHost() + ";DatabaseName=" + requestVo.getDbName();
            driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
        } else if (DbType.getDbType(requestVo.getDbTypeName()) == DbType.POSTGRE_SQL) {
            dbUrl = "jdbc:postgresql://" + requestVo.getHost() + "/" + requestVo.getDbName();
            driver = "org.postgresql.Driver";
        } else {
//            Asserts.fail("暂不支持的数据库类型");
            throw new RuntimeException("暂不支持的数据库类型");
        }
        bo.setDbUrl(dbUrl);
        bo.setDriver(driver);
        bo.setUsername(username);
        bo.setPassword(password);
    }

    // 处理表
    private void handleTable(CodeGeneratorRequestVo requestVo, CodeGeneratorBo bo) {
        bo.setTableNames(SkyStringUtils.split(requestVo.getTableNames()));
        bo.setTablePrefixes(SkyStringUtils.split(requestVo.getTablePrefixes()));
        bo.setFieldPrefixes(SkyStringUtils.split(requestVo.getFieldPrefixes()));
        bo.setExcludeTableNames(SkyStringUtils.split(requestVo.getExcludeTableNames()));
        bo.setIgnoreColumns(SkyStringUtils.split(requestVo.getIgnoreColumns()));
    }


    /**
     * 获取python代码
     * */
    public String getFileContent(String filePath) throws IOException {
        Resource resource = resourceLoader.getResource("classpath:" + filePath);
        URL url = resource.getURL();

        return url.getPath();
    }

}
